# BEGIN BPS TAGGED BLOCK {{{
# 
# COPYRIGHT:
#  
# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC 
#                                          <jesse@bestpractical.com>
# 
# (Except where explicitly superseded by other copyright notices)
# 
# 
# LICENSE:
# 
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
# from www.gnu.org.
# 
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# 
# 
# CONTRIBUTION SUBMISSION POLICY:
# 
# (The following paragraph is not intended to limit the rights granted
# to you to modify and distribute this software under the terms of
# the GNU General Public License and is only of importance to you if
# you choose to contribute your changes and enhancements to the
# community by submitting them to Best Practical Solutions, LLC.)
# 
# By intentionally submitting any modifications, corrections or
# derivatives to this work, or any other work intended for use with
# Request Tracker, to Best Practical Solutions, LLC, you confirm that
# you are the copyright holder for those contributions and you grant
# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
# royalty-free, perpetual, license to use, copy, create derivative
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
# 
# END BPS TAGGED BLOCK }}}

=head1 NAME

RTx::AssetTracker::Interface::Web

=begin testing

use_ok(RTx::AssetTracker::Interface::Web);

=end testing

=cut


package RTx::AssetTracker::Interface::Web;
use strict;


package HTML::Mason::Commands;
use strict;
use vars qw/$r $m %session/;


# {{{ sub LoadAsset - loads a asset

=head2  LoadAsset id

Takes a asset id as its only variable. if it's handed an array, it takes
the first value.

Returns an RTx::AssetTracker::Asset object as the current user.

=cut

sub LoadAsset {
    my $id = shift;

    if ( ref($id) eq "ARRAY" ) {
        $id = $id->[0];
    }

    unless ($id) {
        Abort("No asset specified");
    }

    my $Asset = RTx::AssetTracker::Asset->new( $session{'CurrentUser'} );
    $Asset->Load($id);
    unless ( $Asset->id ) {
        Abort("Could not load asset $id");
    }
    return $Asset;
}

# }}}

# {{{ sub ProcessAssetBasics

=head2 ProcessAssetBasics ( AssetObj => $Asset, ARGSRef => \%ARGS );

Returns an array of results messages.

=cut

sub ProcessAssetBasics {

    my %args = (
        AssetObj => undef,
        ARGSRef   => undef,
        @_
    );

    my $AssetObj = $args{'AssetObj'};
    my $ARGSRef   = $args{'ARGSRef'};

    # {{{ Set basic fields 
    my @attribs = qw(
      Name
      Description
      Parent
      Model
      Location
      Status
      Type
    );

    if ( $ARGSRef->{'Type'} and ( $ARGSRef->{'Type'} !~ /^(\d+)$/ ) ) {
        my $temptype = RTx::AssetTracker::Type->new($RT::SystemUser);
        $temptype->Load( $ARGSRef->{'Type'} );
        if ( $temptype->id ) {
            $ARGSRef->{'Type'} = $temptype->Id();
        }
    }


   # Status isn't a field that can be set to a null value.
   # RT core complains if you try
    delete $ARGSRef->{'Status'} unless ($ARGSRef->{'Status'});
    
    my @results = UpdateRecordObject(
        AttributesRef => \@attribs,
        Object        => $AssetObj,
        ARGSRef       => $ARGSRef
    );

     #}}}

    return (@results);
}

# }}}

# {{{ sub ProcessAssetIPs

=head2 ProcessAssetIPs ( AssetObj => $Asset, ARGSRef => \%ARGS );

Returns an array of results messages.

=cut

sub ProcessAssetIPs {

    my %args = (
        AssetObj => undef,
        ARGSRef   => undef,
        @_
    );

    my $AssetObj = $args{'AssetObj'};
    my $ARGSRef   = $args{'ARGSRef'};

    my @results;
    my %ips;
    foreach my $key ( keys %$ARGSRef ) {

        if ($key =~ /^Asset-(\d+)-DeleteIP-(\d+)$/) {
            my ($rc, $msg) = $AssetObj->DeleteIP(IP => $2);
            push @results, $msg;
            delete $ARGSRef->{$key};
            next;
        }

        next unless ($key =~ /^Asset-(\d+)-Add(Interface|IP|MAC)(\d+)$/);
        $ips{$3}{$2} = $ARGSRef->{$key};
        delete $ARGSRef->{$key};

    }

    foreach my $ip (keys %ips) {
        next unless ( $ips{$ip}{IP} or $ips{$ip}{Interface} or $ips{$ip}{MAC} );
        my (undef, $msg) = $AssetObj->AddIP( IP => $ips{$ip}{IP},
                                             Interface => $ips{$ip}{Interface},
                                             MAC => $ips{$ip}{MAC} );
        push @results, $msg;
    }


    return (@results);
}

# }}}

# {{{ sub ProcessAssetWatchers

=head2 ProcessAssetWatchers ( AssetObj => $Asset, ARGSRef => \%ARGS );

Returns an array of results messages.

=cut

sub ProcessAssetWatchers {
    my %args = (
        AssetObj => undef,
        ARGSRef   => undef,
        @_
    );
    my (@results);

    my $Asset  = $args{'AssetObj'};
    my $ARGSRef = $args{'ARGSRef'};

    # {{{ Munge watchers

    foreach my $key ( keys %$ARGSRef ) {

        # {{{ Delete deletable watchers
        if ( ( $key =~ /^Asset-DeleteWatcher-Type-(.*)-Principal-(\d+)$/ )  ) {
            my ( $code, $msg ) = 
                $Asset->DeleteWatcher(PrincipalId => $2,
                                       Type => $1);
            push @results, $msg;
        }

        # Delete watchers in the simple style demanded by the bulk manipulator
        elsif ( $key =~ /^Delete(Owner|Admin)$/ ) {	    
            my ( $code, $msg ) = $Asset->DeleteWatcher( Email => $ARGSRef->{$key}, Type => $1 );
            push @results, $msg;
        }

        # }}}

        # Add new wathchers
        elsif ( ( $key =~ /^AddWatcher-Type-(Admin|Owner)$/ ) )
        {
            my $type = $1;
            foreach my $watcher (
                ref( $ARGSRef->{$key} ) ? @{ $ARGSRef->{$key} } : ( $ARGSRef->{$key} ) )
            {
                next unless ( $watcher =~ /^Principal-(\d+)$/ );
                my $WatcherId = $1;
                my ( $code, $msg ) = $Asset->AddWatcher(
                    PrincipalId => $WatcherId,
                    Type  => $type
                );
                push @results, $msg;
            }
        }

        #Add requestors in the simple style demanded by the bulk manipulator
        elsif ( $key =~ /^Add(Requestor|Cc|AdminCc)$/ ) {
            my ( $code, $msg ) = $Asset->AddWatcher(
                Type  => $1,
                Email => $ARGSRef->{$key}
            );
            push @results, $msg;
        }

        # Add new  watchers by owner
        elsif ( ( $ARGSRef->{$key} =~ /^(AdminCc|Cc|Requestor)$/ )
            and ( $key =~ /^Asset-AddWatcher-Principal-(\d*)$/ ) ) {

            #They're in this order because otherwise $1 gets clobbered :/
            my ( $code, $msg ) =
              $Asset->AddWatcher( Type => $ARGSRef->{$key}, PrincipalId => $1 );
            push @results, $msg;
        }
    }

    # }}}

    return (@results);
}

# }}}

# {{{ sub CreateAsset

=head2 CreateAsset ARGS

Create a new asset, using Mason's %ARGS.  returns @results.

=cut

sub CreateAsset {
    my %ARGS = (@_);

    my (@Actions);

    my $Asset = new RTx::AssetTracker::Asset( $session{'CurrentUser'} );

    my $Type = new RTx::AssetTracker::Type( $session{'CurrentUser'} );
    unless ( $Type->Load( $ARGS{'Type'} ) ) {
        Abort('Type not found');
    }

    unless ( $Type->CurrentUserHasRight('CreateAsset') ) {
        Abort('You have no permission to create assets of that type.');
    }

    my @Owner;
    my @Admin;

    my %create_args = (
        Type            => $ARGS{'Type'},
        Name            => $ARGS{'Name'},
        Owner           => \@Owner,
        Admin           => \@Admin,
        Description     => $ARGS{'Description'},
        Status          => $ARGS{'Status'},
        Model           => $ARGS{'Model'},
        Location        => $ARGS{'Location'},
        Parent          => $ARGS{'Parent'},
    );
    foreach my $arg (keys %ARGS) {
            next if ($arg =~ /-Magic$/);
       #Object-RT::Ticket--CustomField-3-Values
        if ($arg =~ /^Object-RTx::AssetTracker::Transaction--CustomField-/) {
            $create_args{$arg} = $ARGS{$arg};
        }
        elsif ($arg =~ /^Object-RTx::AssetTracker::Asset--CustomField-(\d+)(.*?)$/) {
            my $cfid = $1;
            my $cf = RTx::AssetTracker::CustomField->new( $session{'CurrentUser'});
            $cf->Load($cfid);

            if ($cf->Type eq 'FreeformMultiple') {
                $ARGS{$arg} =~ s/\r\n/\n/g;
                $ARGS{$arg} = [split('\n', $ARGS{$arg})];
            }

            if ( $arg =~ /-Upload$/ ) {
                $create_args{"CustomField-".$cfid} = _UploadedFile($arg);
            }
            else {
                $create_args{"CustomField-".$cfid} = $ARGS{"$arg"};
            }
        }
        elsif ($arg =~ /^AddWatcher-Type-Owner$/) {
            push(@Owner, map { s/Principal-//; $_ } 
                 ref( $ARGS{$arg} ) ? @{ $ARGS{$arg} } : ( $ARGS{$arg} ) );
        }
        elsif ($arg =~ /^AddWatcher-Type-Admin$/) {
            push(@Admin, map { s/Principal-//; $_ }
                 ref( $ARGS{$arg} ) ? @{ $ARGS{$arg} } : ( $ARGS{$arg} ) );
        }
    }


    my ( $id, $Trans, $ErrMsg ) = $Asset->Create(%create_args);
    unless ( $id && $Trans ) {
        Abort($ErrMsg);
    }

    push ( @Actions, split("\n", $ErrMsg) );
    unless ( $Asset->CurrentUserHasRight('ShowAsset') ) {
        Abort( "No permission to view newly created asset #"
            . $Asset->id . "." );
    }
    return ( $Asset, @Actions );

}

# }}}


eval "require RTx::AssetTracker::Interface::Web_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RTx/AssetTracker/Interface/Web_Vendor.pm});
eval "require RTx::AssetTracker::Interface::Web_Local";
die $@ if ($@ && $@ !~ qr{^Can't locate RTx/AssetTracker/Interface/Web_Local.pm});

1;
